<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of ExportGeneratorTravideclass
 *
 * @author jay
 */
class ExportGeneratorTravide extends ExportGenerator {

    private $exportVersion = 1;
    private $honourPublishSettings = true;
    private $resourceBasePath = '.';
    private $exportResources = false;


    public function setHonourPublishSettings($honourPublishSettings) {
        $this->honourPublishSettings = $honourPublishSettings;
    }

    public function getHonourPublishSettings() {
        return $this->honourPublishSettings;
    }

    public function setExportResources($exportResources) {
        $this->exportResources = $exportResources;
    }

    public function getExportResources() {
        return $this->exportResources;
    }

    public function getResourceBasePath() {
        return $this->resourceBasePath;
    }

    public function setResourceBasePath($resourceBasePath) {
        $this->resourceBasePath = $resourceBasePath;
    }

    private function generatePropertyMasterList(DOMNode $parent, $collectionList) {
        $domElement = $parent->appendChild(new DOMElement('propertyDetails'));
        /**
         * For now just display all the propertyDetail records available
         *
         */
        $propertyDetailsList = Doctrine::getTable('PropertyDetail')->findAll();
        foreach ($propertyDetailsList as $propertyDetail) {
            $propertyElement = $domElement->appendChild(new DOMElement('propertyDetail', $this->encodeSpecialCharacters($propertyDetail->getTypeValue())));
            $propertyElement->setAttribute('name', $this->encodeSpecialCharacters($propertyDetail->getTypeName()));
            $propertyElement->setAttribute('uin', $propertyDetail->getUin());
        }
        $this->resetDoctrineConnection();
    }

    private function generateRelationMasterList(DOMNode $parent, $collectionList) {
        $domElement = $parent->appendChild(new DOMElement('relationTypes'));

        $relationTypesList = Doctrine::getTable('RelationType')->findAll();
        foreach ($relationTypesList as $relationType) {
            $propertyElement = $domElement->appendChild(new DOMElement('relationType', $this->encodeSpecialCharacters($relationType->getTypeValue())));
            $propertyElement->setAttribute('name', $this->encodeSpecialCharacters($relationType->getTypeName()));
            $propertyElement->setAttribute('uin', $relationType->getUin());
            $propertyElement->setAttribute('nameInverse', $this->encodeSpecialCharacters($relationType->getNameInverse()));
            $propertyElement->setAttribute('valueInverse', $this->encodeSpecialCharacters($relationType->getValueInverse()));
        }
        $this->resetDoctrineConnection();
    }

    private function generateCollectionTypeMasterList(DOMNode $parent, $collectionList) {
        $domElement = $parent->appendChild(new DOMElement('collectionTypes'));

        $collectionTypesList = Doctrine::getTable('CollectionType')->findAll();
        foreach ($collectionTypesList as $collectionType) {
            $propertyElement = $domElement->appendChild(new DOMElement('collectionType', $this->encodeSpecialCharacters($collectionType->getTypeValue())));
            $propertyElement->setAttribute('name', $this->encodeSpecialCharacters($collectionType->getTypeName()));
            $propertyElement->setAttribute('uin', $collectionType->getUin());
        }
        $this->resetDoctrineConnection();
    }

    private function generateSubjectTagMasterList(DOMNode $parent, $collectionList) {
        $domElement = $parent->appendChild(new DOMElement('subjectTags'));

        $subjectTagsList = Doctrine::getTable('SubjectTag')->findAll();
        foreach ($subjectTagsList as $subjectTag) {
            $propertyElement = $domElement->appendChild(new DOMElement('subjectTag', $this->encodeSpecialCharacters($subjectTag->getTypeName())));
            $propertyElement->setAttribute('uin', $subjectTag->getUin());
        }
        $this->resetDoctrineConnection();
    }

    private function generateVisibilityLevelMasterList(DOMNode $parent, $collectionList) {
        $domElement = $parent->appendChild(new DOMElement('visibilityLevels'));

        $visibilityLevelsList = Doctrine::getTable('VisibilityLevel')->findAll();
        foreach ($visibilityLevelsList  as $visibilityLevel) {
            $propertyElement = $domElement->appendChild(new DOMElement('visibilityLevel', $this->encodeSpecialCharacters($visibilityLevel->getTypeValue())));
            $propertyElement->setAttribute('name', $this->encodeSpecialCharacters($visibilityLevel->getTypeName()));
            $propertyElement->setAttribute('uin', $visibilityLevel->getUin());
        }
        $this->resetDoctrineConnection();
    }

    private function generateMasterLists(DOMNode $parent, $collectionList) {
        $domElement = $parent->appendChild(new DOMElement('masterData'));

        $this->generatePropertyMasterList($domElement, $collectionList);
        $this->generateRelationMasterList($domElement, $collectionList);
        $this->generateCollectionTypeMasterList($domElement, $collectionList);
        $this->generateSubjectTagMasterList($domElement, $collectionList);
        $this->generateVisibilityLevelMasterList($domElement, $collectionList);
    }

    private function generateXMLForProperties(DOMNode $parent, CollectionItem $collectionItem) {
        $domElement = $parent->appendChild(new DOMElement('properties'));
        /**
         * Collection Properties should use the order by sequencing to ensure
         * properties are exported and then re-imported in the desired order
         */

        foreach (Doctrine::getTable('CollectionProperty')->getCollectionPropertiesQuery($collectionItem,true)->execute() as $collectionProperty) {
            $propertyElement = $domElement->appendChild(new DOMElement('property', $this->encodeSpecialCharacters($collectionProperty->getPropertyValue())));
            $propertyElement->setAttribute('identifier', $this->encodeSpecialCharacters($collectionProperty->getPropertyDetail()->getTypeValue()));
            //$propertyElement->setAttribute('identifierUin',$collectionProperty->getPropertyDetailUin());
            $propertyElement->setAttribute('uin', $collectionProperty->getUin());
        }
    }

    private function generateXMLForRelations(DOMNode $parent, CollectionItem $collectionItem) {
        $domElement = $parent->appendChild(new DOMElement('relations'));

        foreach ($collectionItem->getCollectionRelations() as $collectionRelation) {
            /**
             * The relatedItem must be in the publishable list in order for
             * the relation to be added
             */
            if (in_array($collectionRelation->getRelatedItemUin(), $this->publishableUinList)) {
                $propertyElement = $domElement->appendChild(new DOMElement('relation', $collectionRelation->getRelatedItemUin()));
                $propertyElement->setAttribute('relationType', $this->encodeSpecialCharacters($collectionRelation->getRelationType()->getTypeValue()));
                // $propertyElement->setAttribute('identifierUin',$collectionRelation->getRelationTypeUin());
                $propertyElement->setAttribute('uin', $collectionRelation->getUin());
            }
        }
    }

    private function generateXMLForTags(DOMNode $parent, CollectionItem $collectionItem) {
        $domElement = $parent->appendChild(new DOMElement('tags'));
        foreach ($collectionItem->getCollectionTags() as $collectionTag) {
            $propertyElement = $domElement->appendChild(new DOMElement('tag', $this->encodeSpecialCharacters($collectionTag->getSubjectTag()->getTypeName())));
            //$propertyElement->setAttribute('tagUin',$collectionTag->getSubjectTagUin());
            $propertyElement->setAttribute('uin', $collectionTag->getUin());
        }
    }

    private function generateXMLForResources(DOMNode $parent, CollectionItem $collectionItem) {
        $domElement = $parent->appendChild(new DOMElement('resources'));
        foreach ($collectionItem->getCollectionResources() as $collectionResource) {
            $propertyElement = $domElement->appendChild(new DOMElement('resource'));
            $propertyElement->setAttribute('uin', $collectionResource->getUin());
            $propertyElement->appendChild(new DOMElement('resourceName', $this->encodeSpecialCharacters($collectionResource->getResourceName())));
            $propertyElement->appendChild(new DOMElement('resourceLink', $this->encodeSpecialCharacters($collectionResource->getResourceLink())));
            $propertyElement->appendChild(new DOMElement('originalFilename', $this->encodeSpecialCharacters($collectionResource->getOriginalFilename())));

            $dataElement = $propertyElement->appendChild(new DOMElement('resourceData'));
            $dataElement->setAttribute('base64Encoded', $this->encodeSpecialCharacters($collectionResource->getBase64Encoded()));
            $dataElement->setAttribute('requiresIngest', $this->encodeSpecialCharacters($collectionResource->getRequiresIngest()));
            $dataElement->setAttribute('resourceSize', $this->encodeSpecialCharacters($collectionResource->getResourceSize()));

            if (($this->exportResources) && (file_exists($this->resourceBasePath))) {
                if (!$collectionResource->getRequiresIngest()) {
                    /**
                     * The resource is stored in the database - dump it out
                     * to a file
                     */
                    $dataElement->setAttribute('status', 'exported');
                    file_put_contents($this->resourceBasePath . DIRECTORY_SEPARATOR . 'resource_' . $collectionResource->getUin(), $collectionResource->getResourceData());
                } else {
                    /**
                     * The resource is still on the filesystem - copy it to the
                     * resource output directory
                     */
                    if (file_exists(Doctrine::getTable('CollectionResource')->getResourceUploadDir() . DIRECTORY_SEPARATOR . $collectionResource->getResourceLink())) {
                       /**
                        * Copy the file over to the resource dump folder with the correct name
                        */
                        $dataElement->setAttribute('status', 'exported');
                        copy(Doctrine::getTable('CollectionResource')->getResourceUploadDir() . DIRECTORY_SEPARATOR . $collectionResource->getResourceLink(),
                                $this->resourceBasePath . DIRECTORY_SEPARATOR . 'resource_' . $collectionResource->getUin());
                    } else {
                        /**
                         * REsource coudl not be found
                         * TODO: flag this as a quality check error later on
                         */
                        $dataElement->setAttribute('status', 'not-available');
                    }
                }
                $dataElement->nodeValue = $this->encodeSpecialCharacters('resource_' . $collectionResource->getUin());
            } else {
                $dataElement->setAttribute('status', 'not-available');
            }
        }
    }

    private function generateXMLForCollection(DOMNode $parent, CollectionItem $collectionItem) {
        $domElement = $parent->appendChild(new DOMElement('collectionItem'));
        $domElement->setAttribute('collectionType', $this->encodeSpecialCharacters($collectionItem->getCollectionType()->getTypeValue()));
        $domElement->setAttribute('visibilityLevel', $this->encodeSpecialCharacters($collectionItem->getVisibilityLevel()->getTypeValue()));
        $domElement->setAttribute('uin', $collectionItem->getUin());
        $domElement->setAttribute('createdAt', $this->encodeSpecialCharacters($collectionItem->getCreatedAt()));
        $domElement->setAttribute('updatedAt', $this->encodeSpecialCharacters($collectionItem->getUpdatedAt()));
        $domElement->setAttribute('deletedAt', $this->encodeSpecialCharacters($collectionItem->getDeletedAt()));
        $domElement->setAttribute('applicableStart', $this->encodeSpecialCharacters($collectionItem->getApplicableStart()));
        $domElement->setAttribute('applicableEnd', $this->encodeSpecialCharacters($collectionItem->getApplicableEnd()));
        /**
         * TODO: IF <deletedAt> is not null the don't bother to export the rest
         * of the collection item as it should be removed from the foreign
         * system
         */
        $domElement->appendChild(new DOMElement('collectionName', $this->encodeSpecialCharacters($collectionItem->getCollectionName())));

        $this->generateXMLForProperties($domElement, $collectionItem);
        $this->generateXMLForRelations($domElement, $collectionItem);
        $this->generateXMLForTags($domElement, $collectionItem);
        $this->generateXMLForResources($domElement, $collectionItem);
        /*
         * Reset the Doctrine Connection for each collectionITem 
         * to avoid exceeding number of allocated cursors 
         * 
         * This is a workaround for a known Doctrine on Oracle bug 
         */
        $this->resetDoctrineConnection();
    }

    public function generateExportFromCollections($collectionList) {
        $this->setPublishableUinList($collectionList);
        $exportDoc = new DOMDocument('1.0', 'utf-8');

        $exportDoc->formatOutput = true;
        $domElement = $exportDoc->createElementNS('http://travide.googlecode.com/source/trunk/definitions/TravideExportXML', 'travideExport');
        $domElement->setAttribute('export-version', $this->exportVersion);
        $domElement = $exportDoc->appendChild($domElement);

        $this->generateMasterLists($domElement, $collectionList);

        foreach ($collectionList as $collectionItem) {
            $this->generateXMLForCollection($domElement, $collectionItem);
        }
        return $exportDoc;
    }

}

?>
